#ifndef __TEST_COMMON_H_
#define __TEST_COMMON_H_

#define GREEN "\033[32m"
#define RED "\033[31m"
#define YELLOW "\033[33m"
#define RESET "\033[0m"

// Global test variables
#define GLOBAL_INIT_TEST                                                       \
  static int main_ret = 0;                                                     \
  static int test_count = 0;                                                   \
  static int test_pass = 0;

// Base macro for expectations
#define EXPECT_EQ_BASE(equality, expect, actual, format)                       \
  do {                                                                         \
    test_count++;                                                              \
    if (equality) {                                                            \
      printf(GREEN "PASS: %s:%d: expect: " format " actual: " format RESET     \
                   "\n",                                                       \
             __FILE__, __LINE__, expect, actual);                              \
      test_pass++;                                                             \
    } else {                                                                   \
      printf(RED "FAIL: %s:%d: expect: " format " actual: " format RESET "\n", \
             __FILE__, __LINE__, expect, actual);                              \
      main_ret = 1;                                                            \
    }                                                                          \
  } while (0)

// Basic assertion macros
#define EXPECT_EQ(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d")

#define EXPECT_EQ_FLOAT(expect, actual, epsilon)                               \
  EXPECT_EQ_BASE(((expect) - (actual) < (epsilon)) &&                          \
                     ((actual) - (expect) < (epsilon)),                        \
                 expect, actual, "%f")

#define EXPECT_EQ_STR(expect, actual)                                          \
  EXPECT_EQ_BASE(strcmp(expect, actual) == 0, expect, actual, "%s")

#define EXPECT_NE(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) != (actual), expect, actual, "%d")

#define EXPECT_LT(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) < (actual), expect, actual, "%d")

#define EXPECT_GT(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) > (actual), expect, actual, "%d")

#define EXPECT_LE(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) <= (actual), expect, actual, "%d")

#define EXPECT_GE(expect, actual)                                              \
  EXPECT_EQ_BASE((expect) >= (actual), expect, actual, "%d")

#define EXPECT_TRUE(condition)                                                 \
  EXPECT_EQ_BASE((condition), 1, (condition) ? 1 : 0, "%d")

#define EXPECT_FALSE(condition)                                                \
  EXPECT_EQ_BASE(!(condition), 1, (condition) ? 0 : 1, "%d")

// Output test results
#define OUTPUT_TEST_RESULT()                                                   \
  do {                                                                         \
    printf("%d/%d (%3.2f%%) passed\n", test_pass, test_count,                  \
           test_pass * 100.0 / test_count);                                    \
    if (main_ret != 0) {                                                       \
      printf(RED "Some tests failed!\n" RESET);                                \
    } else {                                                                   \
      printf(GREEN "All tests passed!\n" RESET);                               \
    }                                                                          \
  } while (0)

// Test suite support
#define TEST_SUITE(name) void test_suite_##name(void)

#define RUN_TEST_SUITE(name)                                                   \
  do {                                                                         \
    printf(YELLOW "Running test suite: " #name "\n" RESET);                    \
    test_suite_##name();                                                       \
  } while (0)

// Return main result
#define RETURN_TEST_RESULT() return main_ret

#endif // __TEST_COMMON_H_
